package com.aeye.mbr.common.db;

import com.aeye.mbr.common.util.RedisUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.JdbcUtils;

import javax.sql.DataSource;
import java.sql.*;

/**
 * Created by Administrator on 2018/4/2.
 */
public class KeyInfo {
    private long maxKey;        //当前Sequence载体的最大值
    private long minKey;        //当前Sequence载体的最小值
    private long nextKey;       //下一个Sequence值
    private int poolSize;       //Sequence值缓存大小
    private String keyName;     //Sequence的名称
    private static final String sql_update = "UPDATE upms_seq SET value = value + ? WHERE name = ?";
    private static final String sql_query = "SELECT value FROM upms_seq WHERE name = ?";
    private JdbcTemplate jdbcTemplate;
    public KeyInfo(String keyName, int poolSize,JdbcTemplate jdbcTemplate) throws SQLException {
        this.poolSize = poolSize;
        this.keyName = keyName;
        this.jdbcTemplate  = jdbcTemplate;
        retrieveFromDB();
    }

    public String getKeyName() {
        return keyName;
    }

    public long getMaxKey() {
        return maxKey;
    }

    public long getMinKey() {
        return minKey;
    }

    public int getPoolSize() {
        return poolSize;
    }

    /**
     * 获取下一个Sequence值
     *
     * @return 下一个Sequence值
     * @throws SQLException
     */
    public synchronized long getNextKey() throws SQLException {
        if (nextKey > maxKey) {
            retrieveFromDB();
        }
        return nextKey++;
    }

    /**
     * 执行Sequence表信息初始化和更新工作
     * @throws SQLException
     */
    private void retrieveFromDB() throws SQLException {
        String id = RedisUtil.lockWithTimeout(keyName,2000,500);
        //获取到了锁
        if(null != id){
            Connection conn = null;
            PreparedStatement pstmt_query = null;
            ResultSet rs = null;
            Statement stmt = null;
            PreparedStatement pstmt_up = null;
            try {
                conn = jdbcTemplate.getDataSource().getConnection();
                //查询数据库
                pstmt_query = conn.prepareStatement(sql_query);
                pstmt_query.setString(1, keyName);
                rs = pstmt_query.executeQuery();

                if (rs.next()) {
                    maxKey = rs.getLong(1) + poolSize;
                    minKey = maxKey - poolSize + 1;
                    nextKey = minKey;
                } else {
                    System.out.println("执行Sequence数据库初始化工作！");
                    String init_sql = "INSERT INTO upms_seq (name,value) VALUES('" + keyName + "',1000 + " + poolSize + ")";
                    stmt = conn.createStatement();
                    stmt.executeUpdate(init_sql);
                    maxKey = 1000 + poolSize;
                    minKey = maxKey - poolSize + 1;
                    nextKey = minKey;
                    return;
                }
                //更新数据库
                conn.setAutoCommit(false);
                System.out.println("更新Sequence最大值！");
                pstmt_up = conn.prepareStatement(sql_update);
                pstmt_up.setLong(1, poolSize);
                pstmt_up.setString(2, keyName);
                pstmt_up.executeUpdate();
                conn.commit();
            }catch(Exception e){
                e.printStackTrace();
            }finally {
                RedisUtil.releaseLock(keyName,id);
                JdbcUtils.closeResultSet(rs);
                JdbcUtils.closeStatement(pstmt_query);
                JdbcUtils.closeStatement(pstmt_up);
                JdbcUtils.closeStatement(stmt);
                JdbcUtils.closeConnection(conn);
            }
        }else{
            throw new RuntimeException("获取序列锁失败！");
        }
    }
}